//**************************************************************
//		ApplicationMenu.m
//			AppHider
//
//	Copyright (c) 2008 Metta Media
//
//	Permission is hereby granted, free of charge, to any person obtaining a copy
//	of this software and associated documentation files (the "Software"), to deal
//	in the Software without restriction, including without limitation the rights
//	to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
//	copies of the Software, and to permit persons to whom the Software is
//	furnished to do so, subject to the following conditions:
//
//	The above copyright notice and this permission notice shall be included in
//	all copies or substantial portions of the Software.
//
//	THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
//	IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
//	FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
//	AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
//	LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
//	OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
//	THE SOFTWARE.
//**************************************************************
#import "ApplicationMenu.h"


@implementation ApplicationMenu
- (id) init
{
	self = [super init];
	if (self != nil) {
		appItems = [[NSMutableArray alloc] init];
	}
	return self;
}

- (id) initWithURL:(NSString*)URL withDefaults:(NSDictionary*)defaults
{
	[self init];
	supportFolder = [MABSupportFolder sharedController];
	NSFileManager * fileManager = [NSFileManager defaultManager];
	bundleID = [[NSBundle bundleWithPath: URL] bundleIdentifier];
	[bundleID retain];
	if(![fileManager fileExistsAtPath:URL]){
		NSException* myException = [NSException
									exceptionWithName:@"FileNotFoundException"
									reason:@"File Not Found on System"
									userInfo:nil];
		@throw myException;
	}
	preferences = [[NSMutableDictionary alloc] init];
	name = [fileManager displayNameAtPath:URL];
	[name retain];
	title = @"";
	icon = [[NSWorkspace sharedWorkspace] iconForFile:URL];
	[icon retain];
	customIcon = NO;
	toolTip = @"";
	BOOL items = [[defaults objectForKey:@"Default Items"] boolValue];
	BOOL hideIcon = [[defaults objectForKey:@"Hide dock icon"] boolValue];
	if(items)
	{
		[self setItemsFromArray:[[NSArray alloc] initWithObjects:
							[[NSDictionary alloc] initWithObjectsAndKeys:@"Keystroke", @"action",
							 @"Preferences", @"name",
							 [NSMutableDictionary dictionaryWithObject:[NSMutableArray arrayWithObject:@"command"] forKey:@"modifiers"], @"Preferences",
							 @",", @"value", nil],
							[[NSDictionary alloc] initWithObjectsAndKeys:@"Keystroke", @"action",
							 @"Quit", @"name",
							 [NSMutableDictionary dictionaryWithObject:[NSMutableArray arrayWithObject:@"command"] forKey:@"modifiers"], @"Preferences",
							 @"q", @"value", nil], nil] submenu:NO];
	}
	if(hideIcon)
	{
		if(![self isIconHidden])
		{
			[self toggleIconVisibility];
		}
	}
	return self;
}
								 
- (id) initWithDictionary:(NSDictionary*)dict
{
	[self init];
	supportFolder = [MABSupportFolder sharedController];
	name = [dict objectForKey:@"Default Name"];
	[name retain];
	title = [dict objectForKey:@"Default Title"];
	[title retain];
	bundleID = [dict objectForKey:@"Default ID"];
	[bundleID retain];
	if([dict objectForKey:@"Default Icon"] != nil)
	{
		icon = [[NSImage alloc] initWithData:[dict objectForKey:@"Default Icon"]];
		[icon retain];
		customIcon = YES;
	}
	else
	{
		icon = [[NSWorkspace sharedWorkspace] iconForFile:[[NSWorkspace sharedWorkspace] absolutePathForAppBundleWithIdentifier:bundleID]];
		[icon retain];
		customIcon = NO;
	}
	grayScale = [[dict objectForKey:@"Grayscale Image"] boolValue];
	toolTip = [dict objectForKey:@"Default Tooltip"];
	[toolTip retain];
	preferences = [dict objectForKey:@"Default Preferences"];
	[preferences retain];
	[self setItemsFromArray:[dict objectForKey:@"Items"] submenu:NO];
	
	return self;
}

-(BOOL)isIconHidden
{
	//NSBundle * appBundle = [[NSBundle bundleWithPath:[[NSWorkspace sharedWorkspace] absolutePathForAppBundleWithIdentifier:bundleID]] retain];
	NSString * path = [[[NSWorkspace sharedWorkspace] absolutePathForAppBundleWithIdentifier:bundleID] stringByAppendingString:@"/Contents/Info.plist"];
	if([[NSFileManager defaultManager] fileExistsAtPath:path])
	{
		NSData *plistData;
		NSString *error;
		NSPropertyListFormat format;
		id plist;
		plistData = [NSData dataWithContentsOfFile:path];
		
		plist = [NSPropertyListSerialization propertyListFromData:plistData
												 mutabilityOption:NSPropertyListImmutable
														   format:&format
												 errorDescription:&error];
		if(!plist)
		{
			NSLog(error);
			[error release];
		}
		else
		{
			if([plist objectForKey:@"LSUIElement"] != nil || [plist objectForKey:@"NSUIElement"] != nil)
			{
				if([[plist objectForKey:@"LSUIElement"] intValue] == 1 || [[plist objectForKey:@"NSUIElement"] intValue] == 1)
				{
					return YES;
				}
			}
		}
	}
	return NO;
}

-(void)toggleIconVisibility
{
	NSMutableDictionary * infoDict = [[NSMutableDictionary dictionaryWithContentsOfFile:[[[NSBundle bundleWithIdentifier:bundleID] bundlePath] stringByAppendingString:@"/Contents/Info.plist"]] retain];
	[infoDict setObject:([self isIconHidden]?[NSNumber numberWithInt:0]:[NSNumber numberWithInt:1]) forKey:@"LSUIElement"];
	//[infoDict writeToFile:[[[NSBundle bundleWithIdentifier:bundleID] bundlePath] stringByAppendingString:@"Info.plist"] atomically:YES];
	//NSBundle * appBundle = [[NSBundle bundleWithPath:[[NSWorkspace sharedWorkspace] absolutePathForAppBundleWithIdentifier:bundleID]] retain];
	NSString * path = [[[NSWorkspace sharedWorkspace] absolutePathForAppBundleWithIdentifier:bundleID] stringByAppendingString:@"/Contents/Info.plist"];
	if([[NSFileManager defaultManager] fileExistsAtPath:path])
	{
		NSData *plistData;
		NSString *error;
		NSPropertyListFormat format;
		id plist;
		plistData = [NSData dataWithContentsOfFile:path];
		
		plist = [NSPropertyListSerialization propertyListFromData:plistData
												 mutabilityOption:NSPropertyListMutableContainersAndLeaves//NSPropertyListImmutable
														   format:&format
												 errorDescription:&error];
		if(!plist)
		{
			NSLog(error);
			[error release];
		}
		else
		{
			[plist setObject:([self isIconHidden]?[NSNumber numberWithInt:0]:[NSNumber numberWithInt:1]) forKey:@"LSUIElement"];
			[plist writeToFile:path atomically:YES];
		}
	}
}
	

- (NSString*)name
{
	[name retain];
	return name;
}

-(void)setName:(NSString *)n
{
	name = n;
}

- (NSString*) itemTitle
{
	[title retain];
	return title;
}

- (void) setItemTitle:(NSString *)t
{
	title = t;
}

- (NSString*)bundleID
{
	return bundleID;
}

- (void) setBundleID:(NSString*)p
{
	bundleID = p;
}

- (NSImage*)icon
{
	[icon retain];
	if(![icon isKindOfClass:[NSImage class]])
	{
		//  I am not an image
	}
	return icon;//[[NSImage alloc] initWithSize:NSMakeSize(32,32)];//
}

-(void)setIcon:(id)i
{
	if([i isKindOfClass:[NSData class]])
	{
		[icon release];
		icon = [[NSImage alloc] initWithData:i];
		[icon setSize:NSMakeSize(64, 64)];
		[icon retain];
		customIcon = YES;
	}
	if([i isKindOfClass:[NSImage class]])
	{
		[icon release];
		icon = i;
		[icon setSize:NSMakeSize(64, 64)];
		[icon retain];
		customIcon = YES;
	}
	else
	{
		NSException* myException = [NSException
									exceptionWithName:@"BadImageException"
									reason:@"Image Type Is Not NSData or NSImage"
									userInfo:nil];
		@throw myException;
	}
	[icon retain];
}
- (BOOL) grayScale
{
	return grayScale;
} 

- (void) setGreyScale:(BOOL)value
{
	grayScale = value;
}

- (void)removeIcon
{
	if(customIcon)
	{
		[icon release];
		icon = [[NSWorkspace sharedWorkspace] iconForFile:[[NSWorkspace sharedWorkspace] absolutePathForAppBundleWithIdentifier:bundleID]];
		[icon retain];
		customIcon = NO;
	}
}

- (NSString*)toolTip
{
	return toolTip;
}

-(void)setTooltip:(NSString*)t
{
	toolTip = t;
}

- (NSMutableDictionary*)preferences
{
	return preferences;
}

- (void) setPreferences:(NSMutableDictionary*)prefs
{
	preferences = prefs;
}

- (NSMutableArray*) appItems
{
	return appItems;
}

-(NSMutableArray*)setItemsFromArray:(NSMutableArray*)arr submenu:(BOOL)s
{
	NSMutableArray * newItems = [[NSMutableArray alloc] init];
	//Node *newNode;
	
	for(id currItem in arr) {
		/* newNode = [[Node alloc] init];
				if([[currItem objectForKey:@"action"] isEqualTo:@"Submenu"])
				 {
					 NSMutableArray * submenu = [self setItemsFromArray:[currItem objectForKey:@"value"] submenu:YES];
					 [newNode setChildren:submenu];
				 }
				else
				 {
					 
					 [newNode setItemValue:[currItem objectForKey:@"value"]];
				 } */
		NSLog(@"prefs in appmenu are: %@", [currItem objectForKey:@"preferences"]);
		Node * newNode = [[[Node alloc] initWithName:[[currItem objectForKey:@"name"] retain]
											 Action:[[currItem objectForKey:@"action"] retain]
											  Value:([[currItem objectForKey:@"action"] isEqualTo:@"Submenu"]?[self setItemsFromArray:[currItem objectForKey:@"value"] submenu:YES]:[[currItem objectForKey:@"value"] retain]) 
										Preferences:([currItem objectForKey:@"preferences"]?[[currItem objectForKey:@"preferences"] retain]:nil)
											 Parent:bundleID] retain];
		
		/* [newNode setItemName:[currItem objectForKey:@"name"]];
				[newNode setItemAction:[currItem objectForKey:@"action"]];
				if([currItem objectForKey:@"preferences"]) [newNode setItemPreferences:[currItem objectForKey:@"preferences"]]; */
		[newItems addObject:newNode];
		[newNode release];
	}
	
	if(!s)
	 {
		 appItems = [newItems mutableCopy];
	 }
	return newItems;
}
- (id) appItemAtIndex:(int)i
{
	return [appItems objectAtIndex:i];
}

- (int) indexOfAppItem:(id)n
{
	return [appItems indexOfObject:n];
}

- (void)addAppItem:(Node*)n
{
	[appItems addObject:n];
}

- (void)insertAppItem:(Node*)n atIndex:(int)i
{
	[appItems insertObject:n atIndex:i];
}

- (void)replaceAppItemAtIndex:(int)i withAppItem:(id)n
{
	[appItems replaceObjectAtIndex:i withObject:n];
}

- (void)replaceAppItem:(id)o withAppItem:(id)n
{
	[appItems replaceObjectAtIndex:[appItems indexOfObject:o] withObject:n];
}

- (void)removeAppItem:(id)n
{
	[appItems removeObject:n];
}

- (int)appItemsCount
{
	return [appItems count];
}

-(BOOL)saveAppTo:(NSString*)path extension:(NSString*)ext
{
	//NSBeep();
	NSMutableDictionary * appToSave = [[NSMutableDictionary alloc] init];
	//[appToSave retain];
	[appToSave setObject:name  forKey:@"Default Name"];
	[appToSave setObject:title  forKey:@"Default Title"];
	[appToSave setObject:bundleID forKey:@"Default ID"];
	if(customIcon) [appToSave setObject:[icon TIFFRepresentationUsingCompression:NSTIFFCompressionLZW factor:1.0f] forKey:@"Default Icon"];
	[appToSave setObject:[NSNumber numberWithBool:grayScale]  forKey:@"Grayscale Image"];
	[appToSave setObject:toolTip forKey:@"Default Tooltip"];
	[appToSave setObject:preferences forKey:@"Default Preferences"];
	[appToSave setObject:[self enumerateAppItems:appItems] forKey:@"Items"];
	if(path == nil) path = [NSString stringWithFormat:@"%@/%@.plist", [supportFolder supportFolder], bundleID, nil];
	if([ext isEqualToString:@"app"])
	{
		NSLog(@"i'm here!");
		NSLog(@"from address: %@", [[NSWorkspace sharedWorkspace] absolutePathForAppBundleWithIdentifier:@"com.mettamedia.AppHiderDaemon"]);
		NSLog(@"to address: %@", path);
		
		NSError * error = nil;
		NSFileManager * fm = [NSFileManager defaultManager];
		if(![fm copyItemAtPath:[[NSWorkspace sharedWorkspace] absolutePathForAppBundleWithIdentifier:@"com.mettamedia.AppHiderDaemon"] toPath:path error:&error])
			NSLog(@"error: %@", error);
		
		path = [path stringByAppendingString:@"/Contents/Resources/Applications/"];
		[fm createDirectoryAtPath:path attributes:nil];
		path = [path stringByAppendingString:[NSString stringWithFormat:@"%@.plist", bundleID, nil]];
		NSLog(@"New path: %@", path);
	}
	if([appToSave writeToFile:path atomically:YES]) return YES;
	return NO;
}

- (NSMutableArray*)enumerateAppItems:(NSMutableArray*)items
{
	NSMutableArray * arrToSave = [[[NSMutableArray alloc] init] autorelease];
	NSMutableDictionary * itemDict;
	for (id currItem in items) {
		itemDict = [[NSMutableDictionary alloc] init];
		[itemDict setObject:[currItem itemName]  forKey:@"name"];
		[itemDict setObject:[currItem itemAction]  forKey:@"action"];
		if([[currItem itemAction] isEqualTo:@"Submenu"])
		{
			[itemDict setObject:[self enumerateAppItems:[currItem returnChildren]] forKey:@"value"];
		}
		else
		{
			[itemDict setObject:[currItem itemValue] forKey:@"value"];
		}
		if([currItem returnItemPreferences])
		{
			[itemDict setObject:[currItem returnItemPreferences]  forKey:@"preferences"];
		}
		[arrToSave addObject:itemDict];
		[itemDict release];
	}
	return arrToSave;
}

- (void) dealloc
{
	[self saveAppTo:nil extension:nil];
	[name release];
	[bundleID release];
	[icon release];
	[toolTip release];
	[preferences release];
	[appItems release];
	[super dealloc];
}


@end
